.globl idt, gdt
.globl swapper_pg_dir

#include <linux/segment.h>

.globl startup_32
startup_32:
    movl $(KERNEL_DS), %eax
    mov %ax, %ds
    mov %ax, %es
    mov %ax, %fs
    mov %ax, %gs

    movl $0, %esi
    movl $0x100000, %edi
    movl $0x20000, %ecx
    cld
    rep
    movsd                   # 将内核从0移动到0x100000
    movl $1f, %eax
    subl $0xC0000000, %eax
    jmp *%eax

1:  movl $0x101000, %eax
    movl %eax, %cr3
    movl %cr0, %eax
    orl $0x80000000, %eax
    movl %eax, %cr0
    jmp 1f
1:  movl $1f, %eax
    jmp *%eax
1:  lss stack_start, %esp   # 设置esp和ss

    # 清空0到0xa0000的数据
    xorl %eax, %eax
    movl $0, %edi
    movl $0x90000, %ecx
    cld
    rep
    stosb

    # 初始化bss段
    xorl %eax, %eax
    movl _bss, %edi
    movl _end, %ecx
    subl %edi, %ecx
    cld
    rep
    stosb

    xorl %eax, %eax
1:  incl %eax               # 检查A20是否开启
    movl %eax, 0x0          # 如果没开启则一直循环
    cmpl %eax, 0x100000
    je 1b

    pushl $0
    popfl                   # 初始化eflags

# empty_zero_page的前2k是启动参数，后2k供命令行使用
    movl $0x90000, %esi
    movl $empty_zero_page, %edi
    movl $512, %ecx
    cld
    rep
    movsl
    xorl %eax, %eax
    movl $512, %ecx
    rep
    stosl

    lgdt gdt_descr
    lidt idt_descr
    ljmp $(KERNEL_CS), $1f
1:  movl $(KERNEL_DS), %eax # 重载段寄存器
    mov %ax, %ds
    mov %ax, %es
    mov %ax, %fs
    mov %ax, %gs
    lss stack_start, %esp   # 重新设置esp和ss
    xorl %eax, %eax
    lldt %ax
    pushl %eax
    pushl %eax
    pushl %eax
    cld
    call start_kernel
    jmp .

.org 0x1000
swapper_pg_dir:
    .long 0x102007
    .fill 0x2ff, 4, 0
    .long 0x102007
    .fill 0xff, 4, 0

.org 0x2000
pg0:
    .long 0x000007, 0x001007, 0x002007, 0x003007, 0x004007, 0x005007, 0x006007, 0x007007
    .long 0x008007, 0x009007, 0x00a007, 0x00b007, 0x00c007, 0x00d007, 0x00e007, 0x00f007
    .long 0x010007, 0x011007, 0x012007, 0x013007, 0x014007, 0x015007, 0x016007, 0x017007
    .long 0x018007, 0x019007, 0x01a007, 0x01b007, 0x01c007, 0x01d007, 0x01e007, 0x01f007
    .long 0x020007, 0x021007, 0x022007, 0x023007, 0x024007, 0x025007, 0x026007, 0x027007
    .long 0x028007, 0x029007, 0x02a007, 0x02b007, 0x02c007, 0x02d007, 0x02e007, 0x02f007
    .long 0x030007, 0x031007, 0x032007, 0x033007, 0x034007, 0x035007, 0x036007, 0x037007
    .long 0x038007, 0x039007, 0x03a007, 0x03b007, 0x03c007, 0x03d007, 0x03e007, 0x03f007
    .long 0x040007, 0x041007, 0x042007, 0x043007, 0x044007, 0x045007, 0x046007, 0x047007
    .long 0x048007, 0x049007, 0x04a007, 0x04b007, 0x04c007, 0x04d007, 0x04e007, 0x04f007
    .long 0x050007, 0x051007, 0x052007, 0x053007, 0x054007, 0x055007, 0x056007, 0x057007
    .long 0x058007, 0x059007, 0x05a007, 0x05b007, 0x05c007, 0x05d007, 0x05e007, 0x05f007
    .long 0x060007, 0x061007, 0x062007, 0x063007, 0x064007, 0x065007, 0x066007, 0x067007
    .long 0x068007, 0x069007, 0x06a007, 0x06b007, 0x06c007, 0x06d007, 0x06e007, 0x06f007
    .long 0x070007, 0x071007, 0x072007, 0x073007, 0x074007, 0x075007, 0x076007, 0x077007
    .long 0x078007, 0x079007, 0x07a007, 0x07b007, 0x07c007, 0x07d007, 0x07e007, 0x07f007
    .long 0x080007, 0x081007, 0x082007, 0x083007, 0x084007, 0x085007, 0x086007, 0x087007
    .long 0x088007, 0x089007, 0x08a007, 0x08b007, 0x08c007, 0x08d007, 0x08e007, 0x08f007
    .long 0x090007, 0x091007, 0x092007, 0x093007, 0x094007, 0x095007, 0x096007, 0x097007
    .long 0x098007, 0x099007, 0x09a007, 0x09b007, 0x09c007, 0x09d007, 0x09e007, 0x09f007
    .long 0x0a0007, 0x0a1007, 0x0a2007, 0x0a3007, 0x0a4007, 0x0a5007, 0x0a6007, 0x0a7007
    .long 0x0a8007, 0x0a9007, 0x0aa007, 0x0ab007, 0x0ac007, 0x0ad007, 0x0ae007, 0x0af007
    .long 0x0b0007, 0x0b1007, 0x0b2007, 0x0b3007, 0x0b4007, 0x0b5007, 0x0b6007, 0x0b7007
    .long 0x0b8007, 0x0b9007, 0x0ba007, 0x0bb007, 0x0bc007, 0x0bd007, 0x0be007, 0x0bf007
    .long 0x0c0007, 0x0c1007, 0x0c2007, 0x0c3007, 0x0c4007, 0x0c5007, 0x0c6007, 0x0c7007
    .long 0x0c8007, 0x0c9007, 0x0ca007, 0x0cb007, 0x0cc007, 0x0cd007, 0x0ce007, 0x0cf007
    .long 0x0d0007, 0x0d1007, 0x0d2007, 0x0d3007, 0x0d4007, 0x0d5007, 0x0d6007, 0x0d7007
    .long 0x0d8007, 0x0d9007, 0x0da007, 0x0db007, 0x0dc007, 0x0dd007, 0x0de007, 0x0df007
    .long 0x0e0007, 0x0e1007, 0x0e2007, 0x0e3007, 0x0e4007, 0x0e5007, 0x0e6007, 0x0e7007
    .long 0x0e8007, 0x0e9007, 0x0ea007, 0x0eb007, 0x0ec007, 0x0ed007, 0x0ee007, 0x0ef007
    .long 0x0f0007, 0x0f1007, 0x0f2007, 0x0f3007, 0x0f4007, 0x0f5007, 0x0f6007, 0x0f7007
    .long 0x0f8007, 0x0f9007, 0x0fa007, 0x0fb007, 0x0fc007, 0x0fd007, 0x0fe007, 0x0ff007
    .long 0x100007, 0x101007, 0x102007, 0x103007, 0x104007, 0x105007, 0x106007, 0x107007
    .long 0x108007, 0x109007, 0x10a007, 0x10b007, 0x10c007, 0x10d007, 0x10e007, 0x10f007
    .long 0x110007, 0x111007, 0x112007, 0x113007, 0x114007, 0x115007, 0x116007, 0x117007
    .long 0x118007, 0x119007, 0x11a007, 0x11b007, 0x11c007, 0x11d007, 0x11e007, 0x11f007
    .long 0x120007, 0x121007, 0x122007, 0x123007, 0x124007, 0x125007, 0x126007, 0x127007
    .long 0x128007, 0x129007, 0x12a007, 0x12b007, 0x12c007, 0x12d007, 0x12e007, 0x12f007
    .long 0x130007, 0x131007, 0x132007, 0x133007, 0x134007, 0x135007, 0x136007, 0x137007
    .long 0x138007, 0x139007, 0x13a007, 0x13b007, 0x13c007, 0x13d007, 0x13e007, 0x13f007
    .long 0x140007, 0x141007, 0x142007, 0x143007, 0x144007, 0x145007, 0x146007, 0x147007
    .long 0x148007, 0x149007, 0x14a007, 0x14b007, 0x14c007, 0x14d007, 0x14e007, 0x14f007
    .long 0x150007, 0x151007, 0x152007, 0x153007, 0x154007, 0x155007, 0x156007, 0x157007
    .long 0x158007, 0x159007, 0x15a007, 0x15b007, 0x15c007, 0x15d007, 0x15e007, 0x15f007
    .long 0x160007, 0x161007, 0x162007, 0x163007, 0x164007, 0x165007, 0x166007, 0x167007
    .long 0x168007, 0x169007, 0x16a007, 0x16b007, 0x16c007, 0x16d007, 0x16e007, 0x16f007
    .long 0x170007, 0x171007, 0x172007, 0x173007, 0x174007, 0x175007, 0x176007, 0x177007
    .long 0x178007, 0x179007, 0x17a007, 0x17b007, 0x17c007, 0x17d007, 0x17e007, 0x17f007
    .long 0x180007, 0x181007, 0x182007, 0x183007, 0x184007, 0x185007, 0x186007, 0x187007
    .long 0x188007, 0x189007, 0x18a007, 0x18b007, 0x18c007, 0x18d007, 0x18e007, 0x18f007
    .long 0x190007, 0x191007, 0x192007, 0x193007, 0x194007, 0x195007, 0x196007, 0x197007
    .long 0x198007, 0x199007, 0x19a007, 0x19b007, 0x19c007, 0x19d007, 0x19e007, 0x19f007
    .long 0x1a0007, 0x1a1007, 0x1a2007, 0x1a3007, 0x1a4007, 0x1a5007, 0x1a6007, 0x1a7007
    .long 0x1a8007, 0x1a9007, 0x1aa007, 0x1ab007, 0x1ac007, 0x1ad007, 0x1ae007, 0x1af007
    .long 0x1b0007, 0x1b1007, 0x1b2007, 0x1b3007, 0x1b4007, 0x1b5007, 0x1b6007, 0x1b7007
    .long 0x1b8007, 0x1b9007, 0x1ba007, 0x1bb007, 0x1bc007, 0x1bd007, 0x1be007, 0x1bf007
    .long 0x1c0007, 0x1c1007, 0x1c2007, 0x1c3007, 0x1c4007, 0x1c5007, 0x1c6007, 0x1c7007
    .long 0x1c8007, 0x1c9007, 0x1ca007, 0x1cb007, 0x1cc007, 0x1cd007, 0x1ce007, 0x1cf007
    .long 0x1d0007, 0x1d1007, 0x1d2007, 0x1d3007, 0x1d4007, 0x1d5007, 0x1d6007, 0x1d7007
    .long 0x1d8007, 0x1d9007, 0x1da007, 0x1db007, 0x1dc007, 0x1dd007, 0x1de007, 0x1df007
    .long 0x1e0007, 0x1e1007, 0x1e2007, 0x1e3007, 0x1e4007, 0x1e5007, 0x1e6007, 0x1e7007
    .long 0x1e8007, 0x1e9007, 0x1ea007, 0x1eb007, 0x1ec007, 0x1ed007, 0x1ee007, 0x1ef007
    .long 0x1f0007, 0x1f1007, 0x1f2007, 0x1f3007, 0x1f4007, 0x1f5007, 0x1f6007, 0x1f7007
    .long 0x1f8007, 0x1f9007, 0x1fa007, 0x1fb007, 0x1fc007, 0x1fd007, 0x1fe007, 0x1ff007
    .long 0x200007, 0x201007, 0x202007, 0x203007, 0x204007, 0x205007, 0x206007, 0x207007
    .long 0x208007, 0x209007, 0x20a007, 0x20b007, 0x20c007, 0x20d007, 0x20e007, 0x20f007
    .long 0x210007, 0x211007, 0x212007, 0x213007, 0x214007, 0x215007, 0x216007, 0x217007
    .long 0x218007, 0x219007, 0x21a007, 0x21b007, 0x21c007, 0x21d007, 0x21e007, 0x21f007
    .long 0x220007, 0x221007, 0x222007, 0x223007, 0x224007, 0x225007, 0x226007, 0x227007
    .long 0x228007, 0x229007, 0x22a007, 0x22b007, 0x22c007, 0x22d007, 0x22e007, 0x22f007
    .long 0x230007, 0x231007, 0x232007, 0x233007, 0x234007, 0x235007, 0x236007, 0x237007
    .long 0x238007, 0x239007, 0x23a007, 0x23b007, 0x23c007, 0x23d007, 0x23e007, 0x23f007
    .long 0x240007, 0x241007, 0x242007, 0x243007, 0x244007, 0x245007, 0x246007, 0x247007
    .long 0x248007, 0x249007, 0x24a007, 0x24b007, 0x24c007, 0x24d007, 0x24e007, 0x24f007
    .long 0x250007, 0x251007, 0x252007, 0x253007, 0x254007, 0x255007, 0x256007, 0x257007
    .long 0x258007, 0x259007, 0x25a007, 0x25b007, 0x25c007, 0x25d007, 0x25e007, 0x25f007
    .long 0x260007, 0x261007, 0x262007, 0x263007, 0x264007, 0x265007, 0x266007, 0x267007
    .long 0x268007, 0x269007, 0x26a007, 0x26b007, 0x26c007, 0x26d007, 0x26e007, 0x26f007
    .long 0x270007, 0x271007, 0x272007, 0x273007, 0x274007, 0x275007, 0x276007, 0x277007
    .long 0x278007, 0x279007, 0x27a007, 0x27b007, 0x27c007, 0x27d007, 0x27e007, 0x27f007
    .long 0x280007, 0x281007, 0x282007, 0x283007, 0x284007, 0x285007, 0x286007, 0x287007
    .long 0x288007, 0x289007, 0x28a007, 0x28b007, 0x28c007, 0x28d007, 0x28e007, 0x28f007
    .long 0x290007, 0x291007, 0x292007, 0x293007, 0x294007, 0x295007, 0x296007, 0x297007
    .long 0x298007, 0x299007, 0x29a007, 0x29b007, 0x29c007, 0x29d007, 0x29e007, 0x29f007
    .long 0x2a0007, 0x2a1007, 0x2a2007, 0x2a3007, 0x2a4007, 0x2a5007, 0x2a6007, 0x2a7007
    .long 0x2a8007, 0x2a9007, 0x2aa007, 0x2ab007, 0x2ac007, 0x2ad007, 0x2ae007, 0x2af007
    .long 0x2b0007, 0x2b1007, 0x2b2007, 0x2b3007, 0x2b4007, 0x2b5007, 0x2b6007, 0x2b7007
    .long 0x2b8007, 0x2b9007, 0x2ba007, 0x2bb007, 0x2bc007, 0x2bd007, 0x2be007, 0x2bf007
    .long 0x2c0007, 0x2c1007, 0x2c2007, 0x2c3007, 0x2c4007, 0x2c5007, 0x2c6007, 0x2c7007
    .long 0x2c8007, 0x2c9007, 0x2ca007, 0x2cb007, 0x2cc007, 0x2cd007, 0x2ce007, 0x2cf007
    .long 0x2d0007, 0x2d1007, 0x2d2007, 0x2d3007, 0x2d4007, 0x2d5007, 0x2d6007, 0x2d7007
    .long 0x2d8007, 0x2d9007, 0x2da007, 0x2db007, 0x2dc007, 0x2dd007, 0x2de007, 0x2df007
    .long 0x2e0007, 0x2e1007, 0x2e2007, 0x2e3007, 0x2e4007, 0x2e5007, 0x2e6007, 0x2e7007
    .long 0x2e8007, 0x2e9007, 0x2ea007, 0x2eb007, 0x2ec007, 0x2ed007, 0x2ee007, 0x2ef007
    .long 0x2f0007, 0x2f1007, 0x2f2007, 0x2f3007, 0x2f4007, 0x2f5007, 0x2f6007, 0x2f7007
    .long 0x2f8007, 0x2f9007, 0x2fa007, 0x2fb007, 0x2fc007, 0x2fd007, 0x2fe007, 0x2ff007
    .long 0x300007, 0x301007, 0x302007, 0x303007, 0x304007, 0x305007, 0x306007, 0x307007
    .long 0x308007, 0x309007, 0x30a007, 0x30b007, 0x30c007, 0x30d007, 0x30e007, 0x30f007
    .long 0x310007, 0x311007, 0x312007, 0x313007, 0x314007, 0x315007, 0x316007, 0x317007
    .long 0x318007, 0x319007, 0x31a007, 0x31b007, 0x31c007, 0x31d007, 0x31e007, 0x31f007
    .long 0x320007, 0x321007, 0x322007, 0x323007, 0x324007, 0x325007, 0x326007, 0x327007
    .long 0x328007, 0x329007, 0x32a007, 0x32b007, 0x32c007, 0x32d007, 0x32e007, 0x32f007
    .long 0x330007, 0x331007, 0x332007, 0x333007, 0x334007, 0x335007, 0x336007, 0x337007
    .long 0x338007, 0x339007, 0x33a007, 0x33b007, 0x33c007, 0x33d007, 0x33e007, 0x33f007
    .long 0x340007, 0x341007, 0x342007, 0x343007, 0x344007, 0x345007, 0x346007, 0x347007
    .long 0x348007, 0x349007, 0x34a007, 0x34b007, 0x34c007, 0x34d007, 0x34e007, 0x34f007
    .long 0x350007, 0x351007, 0x352007, 0x353007, 0x354007, 0x355007, 0x356007, 0x357007
    .long 0x358007, 0x359007, 0x35a007, 0x35b007, 0x35c007, 0x35d007, 0x35e007, 0x35f007
    .long 0x360007, 0x361007, 0x362007, 0x363007, 0x364007, 0x365007, 0x366007, 0x367007
    .long 0x368007, 0x369007, 0x36a007, 0x36b007, 0x36c007, 0x36d007, 0x36e007, 0x36f007
    .long 0x370007, 0x371007, 0x372007, 0x373007, 0x374007, 0x375007, 0x376007, 0x377007
    .long 0x378007, 0x379007, 0x37a007, 0x37b007, 0x37c007, 0x37d007, 0x37e007, 0x37f007
    .long 0x380007, 0x381007, 0x382007, 0x383007, 0x384007, 0x385007, 0x386007, 0x387007
    .long 0x388007, 0x389007, 0x38a007, 0x38b007, 0x38c007, 0x38d007, 0x38e007, 0x38f007
    .long 0x390007, 0x391007, 0x392007, 0x393007, 0x394007, 0x395007, 0x396007, 0x397007
    .long 0x398007, 0x399007, 0x39a007, 0x39b007, 0x39c007, 0x39d007, 0x39e007, 0x39f007
    .long 0x3a0007, 0x3a1007, 0x3a2007, 0x3a3007, 0x3a4007, 0x3a5007, 0x3a6007, 0x3a7007
    .long 0x3a8007, 0x3a9007, 0x3aa007, 0x3ab007, 0x3ac007, 0x3ad007, 0x3ae007, 0x3af007
    .long 0x3b0007, 0x3b1007, 0x3b2007, 0x3b3007, 0x3b4007, 0x3b5007, 0x3b6007, 0x3b7007
    .long 0x3b8007, 0x3b9007, 0x3ba007, 0x3bb007, 0x3bc007, 0x3bd007, 0x3be007, 0x3bf007
    .long 0x3c0007, 0x3c1007, 0x3c2007, 0x3c3007, 0x3c4007, 0x3c5007, 0x3c6007, 0x3c7007
    .long 0x3c8007, 0x3c9007, 0x3ca007, 0x3cb007, 0x3cc007, 0x3cd007, 0x3ce007, 0x3cf007
    .long 0x3d0007, 0x3d1007, 0x3d2007, 0x3d3007, 0x3d4007, 0x3d5007, 0x3d6007, 0x3d7007
    .long 0x3d8007, 0x3d9007, 0x3da007, 0x3db007, 0x3dc007, 0x3dd007, 0x3de007, 0x3df007
    .long 0x3e0007, 0x3e1007, 0x3e2007, 0x3e3007, 0x3e4007, 0x3e5007, 0x3e6007, 0x3e7007
    .long 0x3e8007, 0x3e9007, 0x3ea007, 0x3eb007, 0x3ec007, 0x3ed007, 0x3ee007, 0x3ef007
    .long 0x3f0007, 0x3f1007, 0x3f2007, 0x3f3007, 0x3f4007, 0x3f5007, 0x3f6007, 0x3f7007
    .long 0x3f8007, 0x3f9007, 0x3fa007, 0x3fb007, 0x3fc007, 0x3fd007, 0x3fe007, 0x3ff007

.org 0x5000
.globl empty_zero_page
empty_zero_page:

.org 0x6000

.align  4
.word   0
idt_descr:
    .word   256 * 8 - 1
    .long   idt

.align 4
idt:
    .fill 256, 8, 0

.align 4
.word 0
gdt_descr:
    .word   256 * 8 - 1
    .long   gdt

.align  8
gdt:
    .quad   0x0000000000000000  /* NULL descriptor */
    .quad   0x0000000000000000  /* not used */
    .quad   0x00cf9a000000ffff  /* 0x10 kernel 4GB code at 0x00000000 */
    .quad   0x00cf92000000ffff  /* 0x18 kernel 4GB data at 0x00000000 */
    .quad   0x00cffa000000ffff  /* 0x23 user   4GB code at 0x00000000 */
    .quad   0x00cff2000000ffff  /* 0x2b user   4GB data at 0x00000000 */
    .quad   0x0000000000000000  /* not used */
    .quad   0x0000000000000000  /* not used */
    .fill   248, 8, 0
